package com.hwtx.form;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;

import javax.tools.*;
import java.io.File;
import java.net.URI;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

@Configuration
public class DynamicCompilationConfig {

    @Component
    public static class DynamicClassCompiler implements ImportBeanDefinitionRegistrar {

        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            try {
                // Java源代码作为字符串
                String sourceCode = """
                        package dynamic;
                        public class MyClass {
                            public String sayHello() {
                                return "Hello, World from dynamically compiled class!";
                            }
                        }
                        """;

                // 创建一个内存中的Java源文件对象
                JavaSourceFromString javaSource = new JavaSourceFromString("dynamic.MyClass", sourceCode);

                // 获取系统的Java编译器
                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                if (compiler == null) {
                    throw new IllegalStateException("无法获取Java编译器。请确保你正在使用JDK而不是JRE。");
                }

                // 创建标准的文件管理器
                StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

                // 设置输出目录
                File outputDir = Paths.get("target", "classes").toFile();
                fileManager.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, List.of(outputDir));

                // 编译源代码
                Iterable<? extends JavaFileObject> compilationUnits = List.of(javaSource);
                JavaCompiler.CompilationTask task = compiler.getTask(
                    null, // Writer for output messages (can be null)
                    fileManager,
                    null, // Diagnostic listener
                    Arrays.asList("-classpath", System.getProperty("java.class.path")), // Compiler options
                    null, // Classes to process (null means none)
                    compilationUnits // Source files to compile
                );

                boolean success = task.call();

                if (!success) {
                    System.out.println("编译失败");
                    return;
                }

                // 关闭文件管理器
                fileManager.close();

                // 将编译后的类注册为Spring Bean
                registerDynamicBean(registry, "dynamic.MyClass");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void registerDynamicBean(BeanDefinitionRegistry registry, String className) throws Exception {
            // 使用自定义类加载器加载编译后的类
            Class<?> clazz = loadClass(className);

            // 创建BeanDefinition
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            BeanDefinition beanDefinition = builder.getBeanDefinition();

            // 注册Bean
            String beanName = clazz.getSimpleName();
            registry.registerBeanDefinition(beanName, beanDefinition);

            System.out.println("Registered dynamic bean: " + beanName);
        }

        private Class<?> loadClass(String className) throws Exception {
            // 使用自定义类加载器加载编译后的类
            CustomClassLoader classLoader = new CustomClassLoader();
            return classLoader.findClass(className);
        }
    }

    // 内存中的Java源文件对象
    static class JavaSourceFromString extends SimpleJavaFileObject {
        final String code;

        JavaSourceFromString(String name, String code) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
        }
    }

    // 自定义类加载器，用于加载编译后的类
    static class CustomClassLoader extends ClassLoader {
        private static final String CLASS_FILE_PATH = "target/classes/";

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] classData = loadClassData(name);
            return defineClass(name, classData, 0, classData.length);
        }

        private byte[] loadClassData(String className) throws ClassNotFoundException {
            try {
                // 构建类文件路径
                String path = CLASS_FILE_PATH + className.replace('.', '/') + ".class";
                File classFile = new File(path);

                // 读取类文件字节码
                byte[] buffer = new byte[(int) classFile.length()];
                try (java.io.FileInputStream fis = new java.io.FileInputStream(classFile)) {
                    fis.read(buffer);
                }

                return buffer;
            } catch (Exception e) {
                throw new ClassNotFoundException(className, e);
            }
        }
    }
}

// 测试用的主类
